﻿/***********************************************************
Copyright © 2015 Howyoung.
************************************************************
SharpZipLib
Copyright © 2001 Mike Krueger.
************************************************************
You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty.
************************************************************
您可以对所收受的本程序源代码，无论以何种媒介，复制与发布其完
整的复制物，然而您必须以显著及适当的方式在每一份复制物上发布
适当的著作权标示及无担保声明。
***********************************************************/
using ICSharpCode.SharpZipLib.Core;
using ICSharpCode.SharpZipLib.Zip;
using System;
using System.IO;

namespace MinecraftSavesBackup
{
    class Compression
    {
        internal static void DecompressZip(string zipPath, string folderPath, string password = null, bool overwrite = true)
        {
            try
            {
                ZipInputStream z = new ZipInputStream(File.OpenRead(zipPath));
                if (password != null) z.Password = password;
                if (!folderPath.EndsWith("\\")) folderPath += "\\";
                if (!Directory.Exists(folderPath)) Directory.CreateDirectory(folderPath);
                ZipEntry t = default(ZipEntry);
                string fp = null;
                do
                {
                    t = z.GetNextEntry();
                    if (t == null)
                        break;
                    fp = folderPath + t.Name;
                    if (t.IsDirectory && !Directory.Exists(fp))
                    {
                        Directory.CreateDirectory(fp);
                    }
                    else if (t.IsFile)
                    {
                        if ((!File.Exists(fp)) || (File.Exists(fp) & overwrite))
                        {
                            FileStream sw = File.Create(fp);
                            int size = 0;
                            byte[] data = new byte[2049];
                            do
                            {
                                size = z.Read(data, 0, data.Length);
                                if (size == 0)
                                    break;
                                sw.Write(data, 0, size);
                            } while (true);
                            sw.Close();
                            File.SetLastWriteTime(fp, t.DateTime);
                        }
                    }
                } while (true);
                z.Close();
            }
            catch (Exception ex)
            {
                HandlingErrors.Record(ex);
            }
        }


        internal static void CompressFolder(string folderPath, string zipPath, int level = 5, string password = null)
        {
            try
            {
                if (!Directory.Exists(folderPath)) return;
                if (!folderPath.EndsWith("\\")) folderPath += "\\";
                ZipOutputStream z = new ZipOutputStream(File.Create(zipPath));
                z.SetLevel(level);
                if (password != null) z.Password = password;
                string fn = null;
                byte[] buffer = new byte[4097];
                int di = folderPath.Length;

                foreach (string f in Directory.GetFiles(folderPath, "*", SearchOption.TopDirectoryOnly))
                {
                    fn = f.Remove(0, di);
                    z.PutNextEntry(new ZipEntry(fn));
                    using (FileStream fs = File.OpenRead(f))
                    {
                        StreamUtils.Copy(fs, z, buffer);
                    }
                }

                foreach (string d in Directory.GetDirectories(folderPath, "*", SearchOption.AllDirectories))
                {
                    fn = d.Remove(0, di) + "\\";
                    z.PutNextEntry(new ZipEntry(fn));
                    foreach (string f in Directory.GetFiles(d, "*", SearchOption.TopDirectoryOnly))
                    {
                        fn = f.Remove(0, di);
                        z.PutNextEntry(new ZipEntry(fn));
                        using (FileStream fs = File.OpenRead(f))
                        {
                            StreamUtils.Copy(fs, z, buffer);
                        }
                    }
                }
                z.Close();
            }
            catch (Exception ex)
            {
                HandlingErrors.Record(ex);
            }
        }
    }
}
